# coding=utf-8
import os
import random
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

from service.basesv import BaseSV
from service.payment_sv import PaymentSV
from tools.cachedata import CacheData
from tools.cachedataclient import CacheDataClient
from tools.datetime_tools import YYYY_MM_DD, HH
from tools.encrypt import md5_key


class Alipay(BaseSV):
    def init(self, win):
        os.environ["webdriver.chrome.driver"] = self.chromedriver_path
        option = webdriver.ChromeOptions()
        self.count_success = 0  # 统计获取成功的次数
        self.win = win
        self.driver = webdriver.Chrome(executable_path=self.chromedriver_path, chrome_options=option,
                                       desired_capabilities=None)
        return self

    def run(self):
        """
        运行
        :return:
        """
        # 打开登录界面
        self.driver.get(self.alipay_login_url)
        if not self.login_status():
            # 等待进入个人中心
            self.go_user_center()
            # 进入账单页面
            self.go_bill()

        while True:
            if self.safe_page_title.__eq__(self.driver.title):
                # 如果是安全检查就自动循环等待用户操作进入账单页面
                self.win.log("******************请扫码*****************‘安全校验 - 支付宝’")
                PaymentSV().alert_scan_qrcode()
                time.sleep(3)

            elif self.bill_page_title.__eq__(self.driver.title):
                # 如果是账单页就抓取数据
                self.win.log("******************开始监听支付结果*****************")
                # 获取数据
                self.get_data()
                self.driver.refresh()

                self.count_success += 1
                print("监听支付账单次数[" + str(self.count_success) + "]")
                self.win.log("监听支付账单次数[" + str(self.count_success) + "]")

                sleep_time = self.get_sleep_time()
                print("休眠时间：" + str(sleep_time))
                time.sleep(sleep_time)

                # 持续更新cookie 避免过期
                self.save_cookie()

            elif self.safe_check_failed_page_title.__eq__(self.driver.title):
                self.win.log("尝试进入账单页面")
                self.driver.find_element_by_xpath("/html/body/div[2]/div[2]/div/div[2]/ul/li[1]/a").click()
                time.sleep(3)
                self.driver.get(self.alipay_bill_url)
                print('尝试进入账单页面')

    def go_bill(self):
        self.win.log("进入账单页面")
        self.driver.get(self.alipay_bill_url)
        while True:
            if self.bill_page_title.__eq__(self.driver.title):
                break
            time.sleep(0.5)

    def go_user_center(self):
        self.win.log("等待进入个人中心")

        is_notify = True

        while True:
            if is_notify and self.safe_page_title.__eq__(self.driver.title):
                # 如果是安全检查就自动循环等待用户操作进入账单页面
                self.win.log("******************请扫码*****************‘安全校验 - 支付宝’")
                PaymentSV().alert_scan_qrcode()
                is_notify = False
            if self.my_alipay_page_title.__eq__(self.driver.title):
                break
            if self.bill_page_title.__eq__(self.driver.title):
                break
            time.sleep(0.5)

    def login_status(self):
        """
        登录状态检查
        :return: True 登录状态，False 登录过期
        """
        try:
            self.win.log("登录状态检查")
            cookies = CacheData().toObj(CacheDataClient().read()).cookies
            if cookies.__len__() > 0:
                for cookie in cookies:
                    print(cookie)
                    self.driver.add_cookie(cookie)

                self.driver.get(self.alipay_bill_url)
                time.sleep(1)
                if '我的账单 - 支付宝'.__eq__(self.driver.title):
                    return True
        except:
            pass
        return False

    def save_cookie(self):
        """
        缓存cookie用于下次直接启动用，避免重复登录，
        如果超时过期cookie将失去作用，需要重新登录即可
        :return:
        """
        cookies = self.driver.get_cookies()
        print(cookies)
        cache_data = CacheData().toObj(CacheDataClient().read())
        # 清空cookie集合
        del cache_data.cookies[:]
        for cookie in cookies:
            cache_data.cookies.append(cookie)
        CacheDataClient().write(cache_data.toJson())

    def get_sleep_time(self):
        """
        休眠时间范围随机控制
        :param min_sec:最小起始时间单位 S
        :param max_sec:最大终止时间单位 S
        :return: min_sec - max_sec之间的 秒数
        """
        day_clock_start = 7
        day_clock_end = 22

        day_min_sleep_time = 4
        day_max_sleep_time = 10

        night_min_sleep_time = 30
        night_max_sleep_time = 60

        now_hour = HH()
        if day_clock_start <= int(now_hour) and int(now_hour) <= day_clock_end:
            sec = random.uniform(day_min_sleep_time, day_max_sleep_time)
        else:
            sec = random.uniform(night_min_sleep_time, night_max_sleep_time)

        return round(sec, 1)

    def get_data(self):
        """
        账单页面数据处理，默认读取前5条进行处理，避免数据的漏单问题，并对push到服务器的数据进行数据的缓存
        :return:
        """

        for i in range(5):
            # 抓取数据
            trade_no, consume, money, state, date_time, summary, md5_sign = self.__get_data(i + 1)
            print(str(trade_no) + " " + str(consume) + " " + str(money) + " " + str(state) + " " + str(
                date_time) + " " + str(summary) + " " + str(md5_sign))

            is_pushed = PaymentSV().push(trade_no, consume, money, date_time, summary)
            if is_pushed:
                self.win.log("*******************Start 有新的支付*******************")
                self.win.log_simple("          流水号: " + str(trade_no))
                self.win.log_simple("            对方: " + str(consume))
                self.win.log_simple("            金额: " + str(money))
                self.win.log_simple("            状态: " + str(state))
                self.win.log_simple("            时间: " + str(date_time))
                self.win.log_simple("            备注: " + str(summary))
                self.win.log_simple("             MD5: " + md5_sign)
                self.win.log("*******************End 有新的支付*******************")
                self.win.logln()
            else:
                self.win.log_simple("未发现新支付记录")

    def __get_data(self, element):
        '''
        根据循环获取头5条数据信息
        :param element: 元素序号
        :return:
        '''
        # 获取当天的时间
        today_xpath = "/html/body/div[3]/div[1]/div[2]/table/tbody/tr[" + str(element) + "]/td[2]/p[1]"
        today_time_xpath = "/html/body/div[3]/div[1]/div[2]/table/tbody/tr[" + str(element) + "]/td[2]/p[2]"
        summary_xpath = "/html/body/div[3]/div[1]/div[2]/table/tbody/tr[" + str(element) + "]/td[3]/p[1]"
        consume_xpath = "/html/body/div[3]/div[1]/div[2]/table/tbody/tr[" + str(element) + "]/td[3]/p[2]"
        money_xpath = "/html/body/div[3]/div[1]/div[2]/table/tbody/tr[" + str(element) + "]/td[4]/span"
        state_xpath = "/html/body/div[3]/div[1]/div[2]/table/tbody/tr[" + str(element) + "]/td[6]/p[1]"
        trade_no_xpath = '//*[@id="J-tradeNo-' + str(element) + '"]'
        today = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located(
            (By.XPATH, today_xpath)))
        if today:
            today_text = today.text

        # 获取具体时间
        today_time = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located(
            (By.XPATH, today_time_xpath)))
        if today_time:
            today_time_text = today_time.text

        # 获取备注
        summary = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, summary_xpath)))

        if summary:
            summary_text = summary.text

        # 获取对方账户信息 打款或者收款方
        consume = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, consume_xpath)))
        if consume:
            consume_text = consume.text

        # 获取具体的交易金额
        money = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, money_xpath)))
        if money:
            money_text = money.text

        # 获取交易状态
        state = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, state_xpath)))
        if state:
            state_text = state.text

        # 获取交易码
        trade_no = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located((By.XPATH, trade_no_xpath)))
        if trade_no:
            trade_no_text = trade_no.get_attribute("title")

        money_str = (money_text)
        if '-' in money_str:
            money_str = money_str.replace('-', '')
            money_str = money_str.strip()
            money_currency = -float(money_str)
        else:
            money_str = money_str.replace('+', '')
            money_str = money_str.strip()
            money_currency = float(money_str)

        if '今天'.__eq__((today_text).strip()):
            date_time = YYYY_MM_DD() + " " + today_time_text
        else:
            date_time = (today_text).strip() + " " + today_time_text

        md5_sign = md5_key(
            (trade_no_text).strip() + (consume_text).replace(' |', '').strip() + str(
                money_currency) + state_text.strip() + str(date_time).strip() + (
                summary_text).strip())

        return trade_no_text, \
               (consume_text).replace(' |', ''), \
               money_currency, \
               state_text, \
               date_time, \
               summary_text, md5_sign


if __name__ == '__main__':
    Alipay().run()
